/* ----------------------------------------------------------------------
 *	Shadow Quest
 *	Copyright (C) 2009 Prageeth Silva <prageeth@thenewcoders.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  ----------------------------------------------------------------------
 */
package units.villagers;

import map.World;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;

import sq.game.Quest;
import units.Player;
import units.Unit;

/** Represents the Healer characters
 * 
 */
public class Healer extends Villager {

    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private Animation healLeft, healRight, healing;
    private float healRate;

    /** Create a new Villager object (overload).
     * @param type The type of the villager
     * @param x The x coordinate in of the villager
     * @param y The y coordinate in of the villager
     * @param maxHP The maximum HP of the villager
     * @throws SlickException
     */
    public Healer(World world, int team)
            throws SlickException {
        // temporarily make the super class and then replace the images
        super(world, team);
        this.setKillable(false);
        this.setHealRate(0.25f);

        this.setDirectoryPath("assets/units/villagers/elvira/");
        Image img = new Image(this.getDirectoryPath() + "heal_left.png");
        this.setHealLeftAnimation(img);
        this.setHealRightAnimation(img.getFlippedCopy(true, false));
        this.setHealUnitAnimation(new Image(this.getDirectoryPath() + "healhalo.png"));
        this.setName("Elvira");
        this.setAttackType(AttackType.UNATTACKABLE);
        this.finalizeLoading();
        this.standInRandomDirection();

    }

    public Healer(World world)
            throws SlickException {
        this(world, 0);
    }

    /** Update the player's state for a frame.
     * @param world A reference to the world.
     * @param input The input object, used to take the keyboard inputs.
     * @param delta Time passed since last frame (milliseconds).
     */
    @Override
    public void update(Input input, int delta) {

        if (this.isAlive()) {

            Player player = this.getWorld().getPlayer();
            double dist2 = calculateDistanceSqrd(player.getX(), player.getY(), this.getX(), this.getY());

            boolean playerHeal = false;
            boolean elvira = true; // TODO this.getVillagerType() == VillagerType.ELVIRA;

            if (!player.isTeleporting() && player.isAlive() && (dist2 <= Unit.Squared(CLOSE_PROXIMITY))) {
                String str = "";
                if (player.getHP() < player.getMaxHP()) {
                    str = (elvira ? "You're looking much healthier now." : "Neigh!");
                    playerHeal = true;
                } else {
                    str = (elvira ? "Return to me if you ever need healing." : "Neigh!");
                    player.setAddonStatus(false);
                }
                this.healUnit(player, delta);
                this.setDialogue(str);
                if (!this.isDialogueShown()) {
                    this.showDialogue();
                }
                this.setDialogueShown(true);
            } else {
                player.setAddonStatus(false);
                this.setDialogueShown(false);
            }

            if (!playerHeal) {

                dist2 = Unit.Squared(CLOSE_PROXIMITY + VISIBLITY);
                Unit ally = null;

                for (Unit u : this.getWorld().getAllOtherUnits()) {
                    if (this.getWorld().getQuest().getCurrentPlayer().isAlly(u) && u.isAlive()) {
                        double d = calculateDistanceSqrd(u.getX(), u.getY(), this.getX(), this.getY());
                        u.setAddonStatus(false);
                        if (d < dist2) {
                            dist2 = d;
                            ally = u;
                        }
                    }
                }

                if (dist2 <= Unit.Squared(CLOSE_PROXIMITY) && ally.isAlive()) {
                    if (ally.getHP() >= ally.getMaxHP()) {
                        ally.setAddonStatus(false);
                    }
                    this.healUnit(ally, delta);
                } else {
                    if (ally != null) {
                        ally.setAddonStatus(false);
                    }
                }

            }

        }

        super.update(input, delta);

    }

    /** Heal a unit.
     * @param unit The unit to be healed.
     * @param delta Time passed since previous frame (milliseconds).
     */
    private void healUnit(Unit unit, int delta) {
        double dx = unit.getX() - this.getX();
        if (!unit.isTeleporting()) {
            unit.setHP(unit.getHP() + this.getHealRate() * delta);
        }
        if (unit.getHP() >= unit.getMaxHP()) {
            unit.setHP(unit.getMaxHP());
            unit.setAddonStatus(false);
            if (dx < 0) {
                this.lookLeft();
            } else {
                this.lookRight();
            }
        } else { // TODO if ((this.getVillagerType() == VillagerType.ELVIRA)) {
            this.setDisplayAnimation(dx < 0 ? this.getHealLeftAnimation() : this.getHealRightAnimation());
            unit.setAddonAnimation(this.getHealUnitAnimation());
            unit.setAddonStatus(true);
        }
    }

    /* Getter and Setters beyond this point. */
    /** Get the healing animation (only for type ELVIRA).
     * @return The animation.
     */
    private Animation getHealLeftAnimation() {
        return this.healLeft;
    }

    /** Set the healing animation (only for type ELVIRA).
     * @param dialogTimer The dialog timer value.
     */
    private void setHealLeftAnimation(Image image) {
        this.healLeft = new Animation(new SpriteSheet(image, 72, 72), FRAME_SLOW_INTERVAL);
        this.getHealLeftAnimation().setLooping(true);
        this.getHealLeftAnimation().setAutoUpdate(false);
    }

    /** Get the healing animation (only for type ELVIRA).
     * @return The animation.
     */
    private Animation getHealRightAnimation() {
        return this.healRight;
    }

    /** Set the healing animation (only for type ELVIRA).
     * @param dialogTimer The dialog timer value.
     */
    private void setHealRightAnimation(Image image) {
        this.healRight = new Animation(new SpriteSheet(image, 72, 72), FRAME_SLOW_INTERVAL);
        this.getHealRightAnimation().setLooping(true);
        this.getHealRightAnimation().setAutoUpdate(false);
    }

    /** Get the healing animation for the unit.
     * @return The animation.
     */
    private Animation getHealUnitAnimation() {
        return this.healing;
    }

    /** Set the healing animation for.
     * @param dialogTimer The dialog timer value.
     */
    private void setHealUnitAnimation(Image image) {
        this.healing = new Animation(new SpriteSheet(image, 72, 72), FRAME_SLOW_INTERVAL);
        this.getHealUnitAnimation().setLooping(true);
        this.getHealUnitAnimation().setAutoUpdate(false);
    }

    public void setHealRate(float rate) {
        this.healRate = rate;
    }

    public float getHealRate() {
        return this.healRate;
    }
}
